/**
 * com.sony.csl.j2me.net
 *  
 * Description:
 *   Utilities for J2ME CLDC/MIDP applications
 *   
 *   Released under OSS terms (see below) as part of LocationAPITools library:
 *     - http://code.google.com/p/locationapitools
 *   
 *   This code was developed within the scope of the NoiseTube project at
 *   Sony Computer Science Laboratory (CSL) Paris, for more information please refer to: 
 *     - http://noisetube.net
 *     - http://code.google.com/p/noisetube
 *     - http://www.csl.sony.fr
 * 
 * Author:
 *   Matthias Stevens (Sony CSL Paris / Vrije Universiteit Brussel)
 *   Contact: matthias.stevens@gmail.com
 * 	
 * License: 
 *   Copyright 2008-2009 Sony CSL Paris
 * 
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *          http://www.apache.org/licenses/LICENSE-2.0
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package com.sony.csl.j2me.net;

import java.util.Enumeration;
import java.util.Vector;

/**
 * @author mstevens
 *
 */
public abstract class URI
{

	private String protocol;
	private String username;
	private String password;
	private String hostname;
	private int port;
	private String path;
	private Vector keyValuePairs;
	
	/**
	 * @param path
	 * @param port
	 * @param protocol
	 * @param hostname
	 */
	public URI(String protocol, String hostname, int port, String path)
	{
		this.protocol = protocol;
		this.hostname = hostname;
		this.port = port;
		this.path = path;
		keyValuePairs = new Vector();
	}
	
	/**
	 * @param path
	 * @param port
	 * @param protocol
	 * @param hostname
	 */
	public URI(String protocol, String hostname, int port, String path, String username, String password)
	{
		this(protocol, hostname, port, path);
		this.username = username;
		this.password = password;
	}

	/**
	 * @return the protocol
	 */
	public String getProtocol()
	{
		return protocol;
	}

	/**
	 * @return the server
	 */
	public String getHostname()
	{
		return hostname;
	}

	/**
	 * @return the port
	 */
	public int getPort()
	{
		return port;
	}

	/**
	 * @return the path
	 */
	public String getPath()
	{
		return path;
	}

	/**
	 * @return the username
	 */
	public String getUsername()
	{
		return username;
	}

	/**
	 * @return the password
	 */
	public String getPassword()
	{
		return password;
	}

	public void addKeyValuePair(String key, String value)
	{
		keyValuePairs.addElement(new KeyValuePair(key, value));
	}
	
	public abstract Integer getDefaultPort();
	
	public String getURIString()
	{
		StringBuffer bff = new StringBuffer();
		bff.append(protocol + "://");
		if(username != null && password != null)
			bff.append(username + ":" + password + "@");
		bff.append(hostname);
		if(getDefaultPort() != null && port != getDefaultPort().intValue())
			bff.append(port); 
		bff.append("/" + path);
		if(!keyValuePairs.isEmpty())
		{
			bff.append("?");
			Enumeration kvEnum = keyValuePairs.elements();
			while(kvEnum.hasMoreElements())
			{
				KeyValuePair keyValuePair = (KeyValuePair) kvEnum.nextElement();
				bff.append(keyValuePair.getKey() + "=" + keyValuePair.getValue());
				if(kvEnum.hasMoreElements())
					bff.append("&");
			}
		}
		return bff.toString();
	}
	
	protected abstract String escapeCharacters(String uriPart);
	
	public class KeyValuePair
	{
		
		private String key;
		private String value;
		
		/**
		 * @param key
		 * @param value
		 */
		public KeyValuePair(String key, String value)
		{
			this.key = escapeCharacters(key); //!!!
			this.value = escapeCharacters(value); //!!!
		}
		
		/**
		 * @return the key
		 */
		public String getKey()
		{
			return key;
		}
		
		/**
		 * @return the value
		 */
		public String getValue()
		{
			return value;
		}
		
	}
	
}
